package model;

import java.awt.geom.Point2D;

import ctf.model.Side;

/**
 * Abstract class used to operate on Game elements which have the ability to move and
 * maintain strategies.
 * @author N. Bhatia, A. Butt, N. Evans, C. Levesque, P. OKeefe
 *
 */

public abstract class GameEntity implements IVisionObject {
	private double acceleration;
	private double angularVelocity;
	private EntityState currentState;
	private EntityState prevState;
	private Side side;
	private String name;

	public GameEntity(boolean register) {
		currentState = new EntityState();
		prevState = new EntityState();
		//if (register)
			GameEntityManager.Instance().registerGameEntity(this);
	}

	/**
	 * Returns the current position of the entity.
	 * @return The current position.
	 */
	public Point2D getPosition() {
		return this.currentState.getPosition();
	}
	
	/**
	 * Returns the previous position of the entity.
	 * @return The previous position.
	 */
	public Point2D getPreviousPosition() {
		return this.prevState.getPosition();
	}

	/**
	 * Sets the current position of the entity.
	 * @param position The new position of which to update entity.
	 */
	public void setPosition(Point2D position) {
		this.currentState.setPosition(position);
	}
	
	/**
	 * Sets the current position of the entity.
	 * @param x The position x-coordinate of which to update entity.
	 * @param y The position y-coordinate of which to update entity.
	 */
	public void setPosition(double x, double y) {
		this.currentState.setPosition(new Point2D.Double(x,y));
	}
	
	/**
	 * Returns the current speed of the entity.
	 * @return The current speed.
	 */
	public double getSpeed() {
		return this.currentState.getSpeed();
	}

	/**
	 * Sets the current speed of an entity.
	 * @param speed The new speed of which to update the entity.
	 */
	public void setSpeed(double speed) {
		this.currentState.setSpeed(speed);
	}

	/**
	 * Returns the current orientation of the entity.
	 * @return The current orientation.
	 */
	public double getOrientation() {
		return this.currentState.getOrientation();
	}
	
	/**
	 * Sets the current orientation of the entity.
	 * @param orientation The new orientation of which to update the entity.
	 */
	public void setOrientation(double orientation) {
		this.currentState.setOrientation(orientation);
	}

	/**
	 * Returns the current acceleration of the entity.
	 * @return The current acceleration.
	 */
	public double getAcceleration() {
		return this.acceleration;
	}

	/**
	 * Sets the current acceleration of the entity.
	 * @param acceleration The new acceleration.
	 */
	public void setAcceleration(double acceleration) {
		this.acceleration = acceleration;
	}

	/**
	 * Returns the current acceleration of the entity.
	 * @return The current angular velocity.
	 */
	public double getAngularVelocity() {
		return this.angularVelocity;
	}

	/**
	 * Sets the current angular velocity of the entity.
	 * @param angularVelocity The new angular velocity.
	 */
	public void setAngularVelocity(double angularVelocity) {
		this.angularVelocity = angularVelocity;
	}

	/**
	 * Preupdate step.
	 * Required when current buffer has to be swapped with the previous.
	 */
	public void preUpdate() {
		prevState = currentState.clone();
	}

	/**
	 * Reverts the Entity to its previous state.  Can be useful for erroneous movement handling.
	 */
	public void revertToPreviousState() {
		currentState = prevState.clone();
	}

	/**
	 * Removes this entity as a observer off the GameEntityManager
	 */
	public void remove() {
		GameEntityManager.Instance().unregisterGameEntity(this);
	}

	/**
	 * Updates the GameEntity based on a given elapsed time
	 * @param elapsedTimeInMillis The delta time since the last update request
	 */
	public abstract void update(int elapsedTimeInMillis);

	/**
	 * Returns the entities side.
	 * @return The side the entity belongs to.
	 */
	public Side getSide(){
		return this.side;
	}
	
	/**
	 * Sets the entities side
	 * @param side The side on which the entity belongs.
	 */
	public void setSide(Side side){
		this.side = side;
	}
	/**
	 * Sets the name of the entity.
	 * @param name The name of the entity.
	 */
	public void setName(String name) {
		this.name = new String(name);
	}
	
	/**
	 * Gets the name of the entity.
	 */
	public String getName() {
		return this.name;
	}
}
